// utils/bluetoothService.js
import store from '@/store'

class BluetoothService {
	constructor() {
		this.isConnected = false
		this.deviceId = null
		this.serviceId = null
		this.characteristicId = null
		this.connectedDevice = null
		this.callbacks = []
		this.reconnectAttempts = 0
		this.maxReconnectAttempts = 3
		this.dataListener = null
		this.appStateListener = null // 应用状态监听器
	}

	// 初始化蓝牙服务
	init() {
		console.log('蓝牙服务初始化')

		// 监听蓝牙连接断开
		uni.onBLEConnectionStateChange((res) => {
			console.log('蓝牙连接状态变化:', res)
			if (!res.connected) {
				this.isConnected = false
				this.updateConnectionStatus('disconnected')
				this.resetWeightData() // 断开时重置重量
				this.tryReconnect()
			} else {
				this.isConnected = true
				this.updateConnectionStatus('connected')
			}
		})

		// 初始化数据监听
		this.setupDataListener()

		// 监听应用状态变化
		this.setupAppStateListener()
	}
	// 设置应用状态监听
	setupAppStateListener() {
		// 移除之前的监听器
		if (this.appStateListener) {
			uni.offAppHide(this.appStateListener.hide)
			uni.offAppShow(this.appStateListener.show)
		}

		this.appStateListener = {
			hide: () => {
				console.log('App 进入后台')
				// 应用进入后台时，可以暂停一些操作
				this.onAppBackground()
			},
			show: () => {
				console.log('App 回到前台')
				// 应用回到前台时，重新同步状态
				this.onAppForeground()
			}
		}

		uni.onAppHide(this.appStateListener.hide)
		uni.onAppShow(this.appStateListener.show)
	}
	onAppBackground() {
		// 可以在这里暂停重连尝试或其他后台操作
		console.log('应用进入后台，暂停蓝牙相关操作')
	}
	// 应用回到前台
	async onAppForeground() {
		console.log('应用回到前台，重新同步蓝牙状态')

		// 延迟一下，确保系统准备就绪
		setTimeout(async () => {
			try {
				await this.syncBluetoothState()
			} catch (error) {
				console.error('同步蓝牙状态失败:', error)
			}
		}, 1000)

	}

	async syncBluetoothState() {
		console.log('开始同步蓝牙状态到store')

		try {
			// 检查蓝牙适配器状态
			const adapterState = await this.getBluetoothAdapterState()
			console.log('蓝牙适配器状态:', adapterState)

			if (!adapterState.available) {
				// 蓝牙不可用
				this.updateConnectionStatus('bluetooth_off')
				this.updateDeviceName('电子秤')
				return
			}

			// 检查当前连接状态
			if (this.isConnected && this.deviceId) {
				// 服务认为已连接，验证实际连接状态
				try {
					// 尝试获取设备服务来验证连接是否真的有效
					await this.getBLEDeviceServices(this.deviceId)
					console.log('蓝牙连接验证成功，状态已同步')
					this.updateConnectionStatus('connected')
				} catch (error) {
					console.log('蓝牙连接已断开，更新状态')
					this.isConnected = false
					this.updateConnectionStatus('disconnected')
					this.resetWeightData()

					// 尝试重新连接
					this.tryReconnect()
				}
			} else {
				// 服务认为未连接，检查是否有保存的连接信息
				const saved = uni.getStorageSync('bluetoothConnection')
				if (saved && saved.deviceId) {
					console.log('检测到保存的连接信息，尝试恢复状态')
					this.updateDeviceName(saved.deviceName || '电子秤')

					// 更新连接状态为断开，但显示设备名称
					this.updateConnectionStatus('disconnected')

					// 可选：自动尝试重连
					// this.tryReconnect()
				} else {
					// 完全没有连接信息
					this.updateConnectionStatus('disconnected')
					this.updateDeviceName('电子秤')
				}
			}
		} catch (error) {
			console.error('同步蓝牙状态时出错:', error)
			this.updateConnectionStatus('error')
		}
	}


	// 设置数据监听
	setupDataListener() {
		if (this.dataListener) {
			uni.offBLECharacteristicValueChange(this.dataListener)
		}

		this.dataListener = (res) => {
			const value = this.ab2str(res.value)
			console.log('收到蓝牙数据:', value)

			// 调用所有注册的回调
			this.callbacks.forEach(cb => {
				try {
					cb(value)
				} catch (e) {
					console.error('蓝牙数据回调执行错误:', e)
				}
			})

			// 使用store的action来解析重量数据
			this.parseWeightFromData(value)
		}

		uni.onBLECharacteristicValueChange(this.dataListener)
	}
	// 更新连接状态到store
	updateConnectionStatus(status) {
		store.dispatch('weight/updateStatus', status)
		console.log('更新连接状态:', status)

		// 根据状态重置相关数据
		if (status === 'disconnected' || status === 'error') {
			// 断开连接或错误时重置重量数据
			this.resetWeightData()
		}
	}
	// 重置重量数据
	resetWeightData() {
		// 重置重量为0
		store.dispatch('weight/updateWeight', '')
		console.log('重置重量数据')
	}

	// 更新设备名称到store
	updateDeviceName(name) {
		store.commit('weight/SET_DEVICE_NAME', name)
		console.log('更新设备名称:', name)
	}

	// 从蓝牙数据解析重量 - 调用store的action来处理
	parseWeightFromData(data) {
		try {
			// 直接调用store的updateWeight action来处理重量数据
			store.dispatch('weight/updateWeight', data)
			store.dispatch('weight/updateWeightStr', data)
		} catch (e) {
			console.error('解析重量数据失败:', e)
		}
	}

	// 保存连接信息
	saveConnection(deviceId, serviceId, characteristicId, device = null) {
		this.deviceId = deviceId
		this.serviceId = serviceId
		this.characteristicId = characteristicId
		this.isConnected = true
		this.connectedDevice = device

		console.log('保存蓝牙连接信息:', {
			deviceId,
			serviceId,
			characteristicId
		})

		// 更新设备名称到store
		if (device) {
			const deviceName = this.formatDeviceName(device)
			this.updateDeviceName(deviceName)
		}

		// 更新连接状态
		this.updateConnectionStatus('connected')

		// 保存到本地存储
		try {
			uni.setStorageSync('bluetoothConnection', {
				deviceId,
				serviceId,
				characteristicId,
				deviceName: device ? this.formatDeviceName(device) : '',
				timestamp: Date.now()
			})
		} catch (e) {
			console.error('保存蓝牙连接失败:', e)
		}
	}
	// 检查并恢复连接
	async checkConnection() {
		try {
			const saved = uni.getStorageSync('bluetoothConnection')
			console.log('检查保存的连接:', saved)

			if (saved && saved.deviceId) {
				// 更新设备名称
				if (saved.deviceName) {
					this.updateDeviceName(saved.deviceName)
				}

				// 检查蓝牙适配器状态
				const adapterState = await this.getBluetoothAdapterState()
				if (adapterState.available && !this.isConnected) {
					// 更新连接状态为连接中
					this.updateConnectionStatus('connecting')
					// 尝试恢复连接
					await this.restoreConnection(saved)
				} else if (this.isConnected) {
					console.log('蓝牙已连接，无需恢复')
					this.updateConnectionStatus('connected')
				}
			} else {
				// 没有保存的连接，更新状态为未连接
				this.updateConnectionStatus('disconnected')
				this.updateDeviceName('电子秤')
			}
		} catch (e) {
			console.error('检查连接失败:', e)
			this.updateConnectionStatus('error')
		}
	}

	// 清理资源
	destroy() {
		// 清理应用状态监听
		if (this.appStateListener) {
			uni.offAppHide(this.appStateListener.hide)
			uni.offAppShow(this.appStateListener.show)
			this.appStateListener = null
		}

		// 清理数据监听
		if (this.dataListener) {
			uni.offBLECharacteristicValueChange(this.dataListener)
			this.dataListener = null
		}

		console.log('蓝牙服务资源已清理')
	}

	// 获取蓝牙适配器状态
	getBluetoothAdapterState() {
		return new Promise((resolve, reject) => {
			uni.getBluetoothAdapterState({
				success: resolve,
				fail: reject
			})
		})
	}

	// 恢复连接
	async restoreConnection(savedConnection) {
		try {
			const {
				deviceId
			} = savedConnection
			console.log('开始恢复连接:', deviceId)

			// 创建连接
			await this.createBLEConnection(deviceId)

			// 等待设备准备就绪
			await new Promise(resolve => setTimeout(resolve, 1000))

			// 重新发现服务
			const services = await this.getBLEDeviceServices(deviceId)
			console.log('重新发现的服务列表:', services)

			// 寻找合适的服务
			let targetServiceId = savedConnection.serviceId
			let targetCharacteristicId = savedConnection.characteristicId

			// 检查保存的服务是否还存在
			const savedServiceExists = services.some(service => service.uuid === targetServiceId)

			if (!savedServiceExists) {
				console.log('保存的服务不存在，寻找替代服务')
				// 寻找合适的替代服务
				const alternativeService = this.findSuitableService(services)
				if (alternativeService) {
					targetServiceId = alternativeService.uuid
					// 重新发现特征值
					const characteristics = await this.getBLEDeviceCharacteristics(deviceId,
						targetServiceId)
					const notifyChar = this.findNotifyCharacteristic(characteristics)
					if (notifyChar) {
						targetCharacteristicId = notifyChar.uuid
					} else {
						throw new Error('未找到可通知的特征值')
					}
				} else {
					throw new Error('未找到合适的服务')
				}
			}

			// 启用通知
			await this.enableNotification(deviceId, targetServiceId, targetCharacteristicId)

			// 更新保存的连接信息
			this.saveConnection(deviceId, targetServiceId, targetCharacteristicId)
			console.log('蓝牙连接恢复成功')

		} catch (error) {
			console.error('恢复连接失败:', error)
			this.isConnected = false
			this.updateConnectionStatus('error')
			throw error
		}
	}

	// 寻找合适的服务
	findSuitableService(services) {
		// 优先寻找常见的蓝牙串口服务
		const preferredServices = services.filter(service =>
			service.uuid.toLowerCase().includes('ffe0') || // 常见串口服务
			service.uuid.toLowerCase().includes('ffe5') ||
			service.uuid.toLowerCase().includes('fff0') ||
			service.uuid.toLowerCase().includes('ae30') // 其他常见服务
		)

		if (preferredServices.length > 0) {
			console.log('找到优先服务:', preferredServices[0])
			return preferredServices[0]
		}

		// 排除通用服务，使用第一个非通用服务
		const genericServices = [
			'00001800-0000-1000-8000-00805F9B34FB', // Generic Access
			'00001801-0000-1000-8000-00805F9B34FB', // Generic Attribute
			'0000180a-0000-1000-8000-00805F9B34FB' // Device Information
		]

		const nonGenericService = services.find(service =>
			!genericServices.includes(service.uuid.toLowerCase())
		)

		if (nonGenericService) {
			console.log('使用非通用服务:', nonGenericService)
			return nonGenericService
		}

		// 最后使用第一个服务
		console.log('使用第一个服务:', services[0])
		return services[0]
	}

	// 寻找可通知的特征值
	findNotifyCharacteristic(characteristics) {
		return characteristics.find(char =>
			char.properties.notify || char.properties.indicate
		)
	}

	// 创建BLE连接
	createBLEConnection(deviceId) {
		return new Promise((resolve, reject) => {
			uni.createBLEConnection({
				deviceId,
				success: () => {
					console.log('BLE连接创建成功')
					resolve()
				},
				fail: (err) => {
					console.error('BLE连接创建失败:', err)
					reject(err)
				}
			})
		})
	}

	// 启用通知
	enableNotification(deviceId, serviceId, characteristicId) {
		return new Promise((resolve, reject) => {
			uni.notifyBLECharacteristicValueChange({
				deviceId,
				serviceId,
				characteristicId,
				state: true,
				success: () => {
					console.log('蓝牙通知启用成功')
					resolve()
				},
				fail: (err) => {
					console.error('蓝牙通知启用失败:', err)
					reject(err)
				}
			})
		})
	}

	// 尝试重连
	async tryReconnect() {
		if (this.reconnectAttempts >= this.maxReconnectAttempts) {
			console.log('达到最大重连次数，停止重连')
			this.reconnectAttempts = 0
			this.updateConnectionStatus('disconnected')
			this.resetWeightData() // 重连失败时重置重量
			return
		}

		this.reconnectAttempts++
		console.log(`尝试重连，第${this.reconnectAttempts}次`)

		try {
			const saved = uni.getStorageSync('bluetoothConnection')
			if (saved && saved.deviceId) {
				this.updateConnectionStatus('connecting')
				await this.restoreConnection(saved)
				this.reconnectAttempts = 0 // 重置重连计数
			}
		} catch (error) {
			console.error(`第${this.reconnectAttempts}次重连失败:`, error)
			this.updateConnectionStatus('error')
			this.resetWeightData() // 重连失败时重置重量

			// 延迟后再次尝试
			setTimeout(() => {
				this.tryReconnect()
			}, 3000)
		}
	}

	// 断开连接
	disconnect() {
		if (this.deviceId) {
			uni.closeBLEConnection({
				deviceId: this.deviceId,
				success: () => {
					console.log('蓝牙连接已断开')
				}
			})
		}

		this.isConnected = false
		this.deviceId = null
		this.serviceId = null
		this.characteristicId = null
		this.connectedDevice = null
		this.reconnectAttempts = 0

		// 更新store状态
		this.updateConnectionStatus('disconnected')
		this.resetWeightData() // 使用统一的重置方法
		this.updateDeviceName('电子秤')

		// 清除本地存储
		try {
			uni.removeStorageSync('bluetoothConnection')
		} catch (e) {
			console.error('清除蓝牙连接存储失败:', e)
		}
	}
	// 注册数据回调
	onDataReceived(callback) {
		if (typeof callback === 'function') {
			this.callbacks.push(callback)
		}
	}

	// 移除数据回调
	offDataReceived(callback) {
		const index = this.callbacks.indexOf(callback)
		if (index > -1) {
			this.callbacks.splice(index, 1)
		}
	}

	// 发送数据
	sendData(data) {
		if (!this.isConnected || !this.deviceId) {
			console.error('蓝牙未连接，无法发送数据')
			return false
		}

		uni.writeBLECharacteristicValue({
			deviceId: this.deviceId,
			serviceId: this.serviceId,
			characteristicId: this.characteristicId,
			value: this.str2ab(data),
			success: () => {
				console.log('数据发送成功:', data)
			},
			fail: (err) => {
				console.error('数据发送失败:', err)
			}
		})
	}

	// 格式化设备名称
	formatDeviceName(device) {
		if (device.name && device.name.trim() !== '') {
			return device.name
		} else if (device.localName && device.localName.trim() !== '') {
			return device.localName
		} else {
			return '未知设备'
		}
	}

	// 获取设备服务
	getBLEDeviceServices(deviceId) {
		return new Promise((resolve, reject) => {
			uni.getBLEDeviceServices({
				deviceId,
				success: (res) => {
					resolve(res.services)
				},
				fail: reject
			})
		})
	}

	// 获取特征值
	getBLEDeviceCharacteristics(deviceId, serviceId) {
		return new Promise((resolve, reject) => {
			uni.getBLEDeviceCharacteristics({
				deviceId,
				serviceId,
				success: (res) => {
					resolve(res.characteristics)
				},
				fail: reject
			})
		})
	}

	// 工具方法
	str2ab(str) {
		const buf = new ArrayBuffer(str.length)
		const bufView = new Uint8Array(buf)
		for (let i = 0; i < str.length; i++) {
			bufView[i] = str.charCodeAt(i)
		}
		return buf
	}

	ab2str(buffer) {
		const bytes = new Uint8Array(buffer)
		let str = ''
		for (let i = 0; i < bytes.length; i++) {
			str += String.fromCharCode(bytes[i])
		}
		return str
	}
}

// 创建单例
const bluetoothService = new BluetoothService()
export default bluetoothService